import get from 'lodash-es/get.js';
import merge from 'lodash-es/merge.js';
import env from '../../env.js';
import cookie from '../../utils/cookie.js';
import storage from '../../utils/storage.js';
import vueGlobal from '../../vueGlobal.js';
import { REMEMBER_KEY } from '../../config/index.js';
import { hasToken, setToken } from '../../utils/token.js';
import { handleCommonRes } from '../../utils/resolver.js';
import { aesMinEncrypt } from '../../utils/cryptoJs.js';
import { resetPassword } from '../../components/reset-password/index.js';
import { clearRequestCache } from '../../plugins/useRequest.js';
import { login as loginApi, logout as logoutApi } from '../../api/index.js';
import { handleUrl } from '@gis/lib/utils/url.js';

export function isStrongPasswd(passwd) {
  return new RegExp(/^.*(?=.{8,16})(?=.*\d)(?=.*[A-Za-z]+)(?=.*[!@#$%^&*?()]).*$/).test(passwd);
}

export async function checkPasswordStrong(passwd, options, onFail) {
  options = Object.assign(
    { enable: false, validator: null, msg: '密码强度太弱,请设置8~16位包含数字字母特殊字符串的密码' },
    options
  );
  if (options.enable === true) {
    const validate = typeof options.validate === 'function' ? options.validator : isStrongPasswd;
    if (!validate(passwd)) {
      vueGlobal.get('$message').warn(options.msg);
      if (typeof onFail === 'function') {
        onFail();
      }
      return Promise.reject();
    }
  }
  return Promise.resolve();
}

export function getRememberedInfo() {
  return storage.local.getItem(REMEMBER_KEY, {});
}

export function setRememberedInfo(remember, info) {
  if (remember !== false) {
    storage.local.setItem(REMEMBER_KEY, info);
  } else {
    storage.local.removeItem(REMEMBER_KEY);
  }
}

export function getPasswordWrongTime(account) {
  return parseInt(storage.local.getItem(account)) || 0;
}

export function setPasswordWrongTime(account, options) {
  options = Object.assign({ enable: true }, options);
  if (options.enable === true) {
    const n = getPasswordWrongTime(account);
    storage.local.setItem(account, n + 1);
  }
}

export function clearPasswordWrongTime(account, options) {
  options = Object.assign({ enable: true }, options);
  if (options.enable === true) {
    storage.local.removeItem(account);
  }
}

export async function checkPasswordWrongTime(account, options) {
  options = Object.assign({ enable: true, num: 3, msg: '在30分钟内错误登录3次，请30分钟后重试' }, options);
  // 判断当前账号输入密码次数
  if (options.enable === true && getPasswordWrongTime(account) >= options.num) {
    vueGlobal.get('$message').warn(options.msg);
    return Promise.reject();
  }
  return Promise.resolve();
}

export function clearLoginInfo() {
  let rememberData = storage.local.getItem(REMEMBER_KEY);
  clearRequestCache();
  cookie.clear();
  storage.clear();
  vueGlobal.get('$pinia').$reset();
  storage.local.setItem(REMEMBER_KEY, rememberData);
}

export async function login(options) {
  const opt = {
    type: '1',
    account: '',
    password: '',
    remember: false,
    checkPwdWrongTime: { enable: true },
    checkPwdStrong: { enable: true },
    onResetPwd: () => {},
    onSuccess: () => {},
    onFail: () => {},
  };
  options = merge(opt, options);
  const { type, account, password, remember } = options;
  await checkPasswordWrongTime(account, options.checkPwdWrongTime);
  setRememberedInfo(remember, { type, account, password, remember });
  const params = {
    type: type,
    account: account,
    password: aesMinEncrypt(password),
  };
  return await handleCommonRes(loginApi, params, {
    silent: true,
    defaultValue: {},
    onOk: async (res) => {
      let data = (res && res.data) || {};
      clearPasswordWrongTime(account, options.checkPwdWrongTime);
      setToken(get(data, 'access_token'));
      cookie.set('no_login_gis', get(data, 'user.no_login_gis')); //是否进入gis
      cookie.set('no_login_ht', get(data, 'user.no_login_ht')); //是否进入后台
      await checkPasswordStrong(password, options.checkPwdStrong, async () => {
        await resetPassword();
        await logout(false);
        if (typeof options.onResetPwd === 'function') {
          await options.onResetPwd();
        }
      });
      if (typeof options.onSuccess === 'function') {
        await options.onSuccess(data);
      }
    },
    onFail: async (res) => {
      const msg = get(res, 'msg');
      if (msg === '账号或密码错误') {
        await setPasswordWrongTime(account, options.checkPwdWrongTime);
      }
      vueGlobal.get('$message').error(msg || '请求错误,请稍后再尝试!');
      if (typeof options.onFail === 'function') {
        await options.onFail('登录失败!');
      }
    },
  });
}

export function logout(reload) {
  // 清空了token，此时页面上如果还有请求，会导致请求失败，然后执行window.location.reload()到登录页面
  if (reload === true && hasToken()) {
    logoutApi();
  }
  clearLoginInfo();
  if (reload === true) {
    if (env.MICRO_XW_ENV()) {
      window.parent.postMessage('logout', '*');
    } else if (env.DEV) {
      window.location.href = handleUrl(env.BASE_URL + '/login');
    } else {
      window.location.href = handleUrl(env.BASE_URL + '/login');
      // window.location.href = '/login';
    }
  }
}

// 放在这里是避免登录页面上清空storage
// 诚运平台进入 - 不使用免登录地址
export const CY_BACK_URL = 'cyBackUrl'; // 诚运平台 指定 返回地址
export const SELF_BACK_URL = 'selfBackUrl'; // 自己平台 指定 返回地址

// sessionStorage存储 指定 返回地址
export function setStoreBackUrl(cyBackUrl, selfBackUrl) {
  if (cyBackUrl) {
    storage.session.setItem(CY_BACK_URL, cyBackUrl);
  }
  if (selfBackUrl) {
    storage.session.setItem(SELF_BACK_URL, selfBackUrl);
  }
}
// 获取 指定 返回地址
export function getStoreBackUrl(key) {
  const keyEnum = {
    cy: CY_BACK_URL,
    self: SELF_BACK_URL,
  };
  return storage.session.getItem(keyEnum[key]);
}
